/**
 * 事件的相关方法
 */

import QilinElement from "./element.js";
import QilinCommon from "./common.js";
import QilinData from "./data.js";

// 解析绑定事件名称字符串
const analysisEventName=(eventName)=>{
    let eventNames=eventName.split(",");
    let result=[];
    eventNames.forEach((item)=>{
        let arr=item.split(".");
        let obj={
            eventName:arr[0]
        };
        if(arr.length > 1){ // 添加事件唯一标识，在事件解绑时很有用
            obj.guid=arr[1];
        };
        result.push(obj);
    });
    return result;
};
// 该元素添加单个事件
const addEventListener=(element,eventName,guid,fn,options)=>{
    // 获取该元素上已定义的事件对象--{click_0:{type:"click",fn:fn}}
    let events=QilinData.getNodeData(element,"Qilin-defined-events") || {};
    if(!guid){ //若事件名未指定唯一标识guid
        // 获取该元素上记录的guid值--无则取0
        guid=QilinData.getNodeData(element,"Qilin-event-guid") || 0;
        // 更新guid值--每次+1
        QilinData.setNodeData(element,"Qilin-event-guid",guid+1);
    };
    // 更改guid，结合事件名称作为存储的key值
    guid=eventName+"_"+guid;
    // 若该元素上已经含有同guid且同类型的事件，则先移除
    if(events[guid] && events[guid].type === eventName){
        element.removeEventListener(eventName,events[guid].fn,events[guid].options);
    };
    // 添加事件
    element.addEventListener(eventName,fn,options);
    events[guid]={
        type:eventName,
        fn,
        options
    };
    QilinData.setNodeData(element,"Qilin-defined-events",events);
};
// 更新事件对象，移除空元素
const updateEvents=(events)=>{
    let obj={};
    let eventsArr=Object.keys(events);
    eventsArr.forEach((item)=>{
        if(events[item]){
            obj[item]=events[item];
        };
    });
    return obj;
};
// 移除元素的单个事件
const removeEventListener=(element,eventName,guid)=>{
    let events=QilinData.getNodeData(element,"Qilin-defined-events");
    let eventsArr=Object.keys(events);
    eventsArr.forEach((item)=>{
        if(events[item].type === eventName){
            // 若有guid则移除指定该唯一标识的事件，否则移除全部该类型事件
            if(guid){
                if(item === eventName+"_"+guid){
                    element.removeEventListener(events[item].type,events[item].fn,events[item].options);
                    events[item]=undefined;
                };
            }else{
                element.removeEventListener(events[item].type,events[item].fn,events[item].options);
                events[item]=undefined;
            };
        };
    });
    // 更新events
    events=updateEvents(events);
    QilinData.setNodeData(element,"Qilin-defined-events",events);
};

export default {
    /**
     * 给某个元素绑定指定事件
     * @param {Element} element 元素节点
     * @param {String} eventName 事件名
     * @param {Function} fn 函数
     * @param {Object} options 参数项
     * @returns 无返回值
     */
    on(element,eventName,fn,options){
        if(!QilinElement.isElement(element) && element !== window){
            throw new TypeError("第一个参数须为元素节点");
        }else if(!eventName || typeof eventName !== "string"){
            throw new TypeError("第二个参数必传且须为字符串");
        }else if(!fn || typeof fn !== "function"){
            throw new TypeError("第三个参数必传且须为function类型");
        }else if(!QilinCommon.isObject(options)){
            options={};
        };
        // 解析eventName，获取事件数组以及guid标志
        const result=analysisEventName(eventName);
        // 批量添加事件
        result.forEach((item)=>{
            addEventListener(element,item.eventName,item.guid,fn.bind(element),options);
        });
    },
    /**
     * 给某个元素解绑指定事件
     * @param {Element} element 元素节点
     * @param {String} eventName 事件名
     * @returns 无返回值
     */
    off(element,eventName){
        if(!QilinElement.isElement(element) && element !== window){
            throw new TypeError("第一个参数须为元素节点");
        }else{
            let events=QilinData.getNodeData(element,"Qilin-defined-events");
            if(events){
                if(!eventName){ //若事件名称不存在，则移除该元素的全部事件
                    let eventsArr=Object.keys(events);
                    eventsArr.forEach((item)=>{
                        element.removeEventListener(events[item].type,events[item].fn,events[item].options);
                    });
                    QilinData.removeNodeData(element);
                }else{ //移除相关指定事件
                    // 解析eventName，获取事件数组以及guid标志
                    const result=analysisEventName(eventName);
                    // 批量添加事件
                    result.forEach((item)=>{
                        removeEventListener(element,item.eventName,item.guid);
                    });
                };
            };
        };
    }
};